package com.fz.study.project.filter;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.fz.study.project.entity.Result;
import com.fz.study.project.entity.dto.UserDTO;
import com.fz.study.project.exception.BizException;
import com.fz.study.project.utils.JwtUtils;
import com.fz.study.project.utils.RedisConstants;
import com.fz.study.project.utils.UserHolder;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

//过滤器
@WebFilter(urlPatterns = "/*")
@RequiredArgsConstructor
@Slf4j
public class JwtFilter implements Filter {
    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("拦截器启动了！");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
//        获取url信息
        String url = request.getRequestURL().toString();
//        判断url中是否包含登录信息
        if (url.contains("login") || url.contains("swagger")
                || url.contains("docs") || url.contains("user")
                || url.contains("index")){
//            包含就放行
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
//        获取登陆信息的jwt信息
        String jwt = request.getHeader("token");
//        判断jwt是否为空
        if (!StringUtils.hasLength(jwt)){
            Result notLogin = Result.error("未登录");
//            将对象转变成json数据传递给前端
            String error = JSONObject.toJSONString(notLogin);
//            响应给前端
            response.getWriter().write(error);
            return;
        }
//        校验jwt数据的有效性
        try {
            JwtUtils.parseJwt(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            Result notLogin = Result.error("令牌有效性异常！");
//            将对象转变成json数据传递给前端
            String error = JSONObject.toJSONString(notLogin);
//            响应给前端
            response.getWriter().write(error);
            return;
        }
        String key = RedisConstants.LOGIN_USER_KEY  + jwt;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
//        log.info("userMap:{}",userMap);
        if (userMap.isEmpty()){
            Result notLogin = Result.error("用户信息为空！");
//            将对象转变成json数据传递给前端
            String error = JSONObject.toJSONString(notLogin);
//            响应给前端
            response.getWriter().write(error);
            return;
        }
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
//        存储到threadLocal中
        UserHolder.saveUser(userDTO);
//        刷新时间
        stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL,TimeUnit.MINUTES);
//        放行
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
        System.out.println("拦截器关闭了！");
    }
}
